package fr.uvsq.isty.bdh.hchess.gui;

import fr.uvsq.isty.bdh.hchess.engine.Engines;
import fr.uvsq.isty.bdh.hchess.engine.GameData;
import fr.uvsq.isty.bdh.hchess.gui.game.GameDisplay;
import fr.uvsq.isty.bdh.hchess.gui.game.RemoveEngineDialog;
import fr.uvsq.isty.bdh.hchess.gui.game.ReplayToolBar;
import fr.uvsq.isty.bdh.hchess.gui.menu.MainMenu;
import fr.uvsq.isty.bdh.hchess.gui.menu.SaveItemMenu;
import fr.uvsq.isty.bdh.hchess.gui.style.RadioListener;
import fr.uvsq.isty.bdh.hchess.gui.style.Style;
import fr.uvsq.isty.bdh.hchess.ranking.Player;
import fr.uvsq.isty.bdh.hchess.ranking.Players;
import java.awt.BorderLayout;
import java.awt.event.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;

/**
 * Main window.
 * Contains all the layout, panels and listeners for interactions.
 *
 * @version 1.0
 * @author Florent Hemmi <florent.hemmi@gmail.com>
 */
public final class MainWindow extends JFrame {
      
    // Attributes declaration
    private JMenuItem itemAbout;
    private JMenuItem itemBack;
    private JMenuItem itemQuit;
    private SaveItemMenu itemSave;
    private JMenuItem itemInstallEngine;
    private JMenuItem itemRemoveEngine;
    private JCheckBoxMenuItem itemEnableHint;
    private JMenuBar menuBar;
    private JMenu menuFile;
    private JMenu menuEngine;
    private JMenu menuStyle;
    private JMenu menuHelp;
    private List<JRadioButtonMenuItem> itemsStyle;
    private ButtonGroup buttonGroupStyle;
    private JFileChooser fileChooser;
    private GameDisplay gameDisplay;
    
    
    /**
     * Profile part of the menu.
     */
    private JMenu menuProfile;
    
    /**
     * Option to create a profile
     */
    private JMenuItem itemCreateProfile;
    
    private GameData gameData;
    
    private JPanel replayModePanel;
    // End of variables declaration

    /**
     * Creates new form MainWindow
     */
    public MainWindow() {        
        MainMenu menu = new MainMenu(this);
        gameData = new GameData(this);
        gameDisplay = new GameDisplay(this);
        replayModePanel = new JPanel();
        
        initComponents();
        this.setContentPane(menu);

        this.pack();
        this.setVisible(true);
        //setLookAndFeel("Windows");
    }

    /**
     * This method is called from within the constructor to initialize the form.
     */
    private void initComponents() {
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setTitle("Chess");

        createMenu();
        createReplayModeDisplay();
    }

    /**
     * Create the menu for user interactions.
     */
    private void createMenu() {
        menuBar = new JMenuBar();
        menuFile = new JMenu();
        itemSave = new SaveItemMenu(gameData);
        itemQuit = new JMenuItem();
        itemBack = new JMenuItem();
        fileChooser = new JFileChooser();

        menuFile.setMnemonic('F');
        menuFile.setText("File");
        
        itemBack.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_B, InputEvent.CTRL_MASK));
        itemBack.setText("Back to menu");
        itemBack.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                gameData.endAnything();
                MainWindow.this.setContentPane(new MainMenu(MainWindow.this));
            	MainWindow.this.setVisible(true);
            	MainWindow.this.repaint();
            }
        });
        menuFile.add(itemBack);

        menuFile.add(itemSave);

        itemQuit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, InputEvent.CTRL_MASK));
        itemQuit.setText("Quit");
        itemQuit.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
            	System.exit(0);
            }
        });
        menuFile.add(itemQuit);

        menuBar.add(menuFile);

        createProfileMenu();
        createEngineMenu();
        createStyleMenu();
        createHelpMenu();

        setJMenuBar(menuBar);
    }
    
    private void createHelpMenu() {
        menuHelp = new JMenu();
        itemEnableHint = new JCheckBoxMenuItem();
        itemAbout = new JMenuItem();
        
        menuHelp.setMnemonic('H');
        menuHelp.setText("Help");
        
        itemEnableHint.setText("Enable hint");
        itemEnableHint.setSelected(true);
        itemEnableHint.addItemListener(new ItemListener() {
            public void itemStateChanged(ItemEvent e) {
                if (e.getStateChange() == 1) gameData.enableHelp(true);
                else gameData.enableHelp(false);
            }
        });
        menuHelp.add(itemEnableHint);

        itemAbout.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0));
        itemAbout.setText("About");
        menuHelp.add(itemAbout);

        menuBar.add(menuHelp);
    }
    
    private void createEngineMenu() {
        menuEngine = new JMenu();
        itemInstallEngine = new JMenuItem();
        itemRemoveEngine = new JMenuItem();
        
        menuEngine.setText("Engine");
        itemInstallEngine.setText("Install an engine");
        itemInstallEngine.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                String name = JOptionPane.showInputDialog(null,
                        "Engine name",
                        "Engine", 
                        JOptionPane.QUESTION_MESSAGE);
                if (name != null) {
                    int returnVal = fileChooser.showOpenDialog(MainWindow.this);

                    if (returnVal == JFileChooser.APPROVE_OPTION) {
                        File file = fileChooser.getSelectedFile();

                        try {
                            if (Engines.getInstance().addEngine(name, file.getPath())) {
                                JOptionPane.showMessageDialog(null,
                                    "Engine successfully installed!",
                                    "Engine",
                                    JOptionPane.INFORMATION_MESSAGE);
                            }
                            else {
                                JOptionPane.showMessageDialog(null,
                                    "Engine already exist!",
                                    "Engine",
                                    JOptionPane.WARNING_MESSAGE);
                            }
                        } catch (IOException ex) {
                            JOptionPane.showMessageDialog(null,
                                    "Engine cannot be created!",
                                    "Engine",
                                    JOptionPane.ERROR_MESSAGE);
                        }
                    } else {
                        // Cancel by user.
                    }
                }
            }
        });
        
        menuEngine.add(itemInstallEngine);
        
        itemRemoveEngine.setText("Remove an engine");
        itemRemoveEngine.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                RemoveEngineDialog ed = new RemoveEngineDialog(null, "Remove an engine", true);
            }
        });
        
        menuEngine.add(itemRemoveEngine);
        menuBar.add(menuEngine);
    }
    
    /**
     * Create the profiles menu in the menu bar.
     * It also add the new profile, checking it has not a reserved name.
     */
    private void createProfileMenu()
    {
    	menuProfile = new JMenu();
    	itemCreateProfile = new JMenuItem();
    	
    	menuProfile.setText("Profile");
    	itemCreateProfile.setText("Create a profile");
    	
    	itemCreateProfile.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                String name = JOptionPane.showInputDialog(null,
                        "Nickname:",
                        "Profile", 
                        JOptionPane.QUESTION_MESSAGE);
                
                if (name != null) {
                    //Special cases
                    if(name.equals("guest") ||  name.equals("") )
                    {
                        JOptionPane.showMessageDialog(null,
                                "Profile name is not valid !",
                                "Profile",
                                JOptionPane.ERROR_MESSAGE);
                    }
                    //Normal
                    else
                    {
                        try {
                            boolean alreadyExists = Players.getInstance().addPlayer( new Player(name) );
                            Players.getInstance().Save();

                            //Success
                            if(!alreadyExists) {
                                JOptionPane.showMessageDialog(null, "Profile succesfully created !", "Profile", JOptionPane.INFORMATION_MESSAGE); }
                            //failure
                            else {
                                JOptionPane.showMessageDialog(null, "Profile already exist !", "Profile", JOptionPane.ERROR_MESSAGE);
                            }
                        } catch (IOException e1) {
                            JOptionPane.showMessageDialog(null, "Profile creation failed !", "Profile", JOptionPane.ERROR_MESSAGE);
                        }
                    }
                }
            }
        });
    	
    	menuProfile.add(itemCreateProfile);
    	menuBar.add(menuProfile);
    	
    }

    /**
     * Create the style menu.
     */
    private void createStyleMenu() {
        try {
            int index = 0;
            Style style = Style.getInstance();
            menuStyle = new JMenu("Style");
            itemsStyle = new ArrayList<JRadioButtonMenuItem>();
            buttonGroupStyle = new ButtonGroup();

            for (String itemString : style.list()) {
                itemsStyle.add(new JRadioButtonMenuItem(style.getFullStyleName(itemString)));
                JRadioButtonMenuItem item = itemsStyle.get(index);
                item.setActionCommand(itemString);
                item.addActionListener(new RadioListener(this));
                buttonGroupStyle.add(item);
                menuStyle.add(item);
                
                // Select current style.
                if (itemString.equals(style.getCurrentStyleName())) {
                    itemsStyle.get(index).setSelected(true);
                }
                index++;
            }
            menuBar.add(menuStyle);
        } catch (IOException ex) {}
    }

    /**
     * Method for setting the look and feel.
     *
     * @param s Name of the look and feel
     */
    private void setLookAndFeel(String s) {
        try {
            for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                if (s.equals(info.getName())) {
                    UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(MainWindow.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(MainWindow.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(MainWindow.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(MainWindow.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
    }
    
    public void createReplayModeDisplay() {
        ReplayToolBar replayToolBar = new ReplayToolBar(gameData);
        replayModePanel.setLayout(new BorderLayout());
        replayModePanel.add(gameDisplay, BorderLayout.CENTER);
        replayModePanel.add(replayToolBar, BorderLayout.SOUTH);
        gameData.addObserver(replayToolBar);
    }
       
    public void switchtoMenuMode() {
        
    }
    
    public void switchToGameMode() {
        setContentPane(gameDisplay);
        setVisible(true);
        repaint();
    }
    
    public void switchToReplayMode() {
        replayModePanel.add(gameDisplay, BorderLayout.CENTER);
        setContentPane(replayModePanel);
        setVisible(true);
        repaint();
    }
    /**
     * @return the gameDisplay
     */
    public GameDisplay getGameDisplay() {
        return gameDisplay;
    }

    public GameData getGameData() {
        return gameData;
    }
    
    public SaveItemMenu getItemSave() {
        return itemSave;
    }
}
